import React from 'react'
import Lighthouse from 'ASSET/img/Lighthouse1.jpg'
import Koala from 'ASSET/img/Koala1.jpg'
import Desert from 'ASSET/img/Desert1.jpg'
import Jellyfish from 'ASSET/img/Jellyfish1.jpg'
import Penguins from 'ASSET/img/Penguins1.jpg'
import Hydrangeas from 'ASSET/img/Hydrangeas1.jpg'
import { mat4 } from './glMartix'
import cubedata from './cubedata.json'
import { gltMakeShadowMatrix } from './martixHelper'
/**
 * 本组件为欢迎页（首页）
 * 由于几乎没有交互逻辑
 * 因此可以不使用类的写法
 * 
 * 实际上，ES6 的类经由 Babel 转码后
 * 其实还是返回一个类似的函数
 */
const shadervs = `

attribute vec3 v3Position;
uniform mat4 um4Rotate;
varying vec3 v_texCoord;
uniform int uiShadowMode;
uniform mat4 um4Shadow;

void main(void)
{
    if(uiShadowMode == 0)
    {
        v_texCoord = v3Position;
        gl_Position = um4Rotate * vec4(v3Position, 1.0);
    }
    else if(uiShadowMode == 1) gl_Position = um4Shadow * um4Rotate * vec4(v3Position, 1.0);
    else gl_Position = vec4(v3Position, 1.0);
}
       `

const shaderfs = `
   #ifdef GL_FRAGMENT_PRECISION_HIGH
   precision highp int;
    precision highp float;
#else
    precision mediump float;
    precision mediump int;
#endif
uniform samplerCube s_texture;
varying vec3 v_texCoord;
uniform int uiShadowMode;

void main(void)
{
    if(uiShadowMode == 0) gl_FragColor = textureCube(s_texture, v_texCoord);
    else if(uiShadowMode == 1) gl_FragColor = vec4(0.7, 0.7, 0.7, 1.0);
    else gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
       `
class WebGL extends React.Component {
  constructor() {
    super()
  }

  componentDidMount() {
    Promise.all([new Promise((reslove, reject) => {
      this.refs.img1.onload = () => {
        reslove()
      }
    }),
    new Promise((reslove, reject) => {
      this.refs.img2.onload = () => {
        reslove()
      }
    }),
    new Promise((reslove, reject) => {
      this.refs.img3.onload = () => {
        reslove()
      }
    }),
    new Promise((reslove, reject) => {
      this.refs.img4.onload = () => {
        reslove()
      }
    }),
    new Promise((reslove, reject) => {
      this.refs.img5.onload = () => {
        reslove()
      }
    }),
    new Promise((reslove, reject) => {
      this.refs.img6.onload = () => {
        reslove()
      }
    })]).then(this.init)
    
  }
  loaddata = () => {
    const img1 = this.refs.img1
    const img2 = this.refs.img2
    const img3 = this.refs.img3
    const img4 = this.refs.img4
    const img5 = this.refs.img5
    const img6 = this.refs.img6
    const webgl = this.refs.myCanvas.getContext('experimental-webgl')
    var jsArrayData = cubedata.data

    this.cubeBuffer = webgl.createBuffer()
    webgl.bindBuffer(webgl.ARRAY_BUFFER, this.cubeBuffer)
    webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData), webgl.STATIC_DRAW)
    const jsCubeIndex = cubedata.cubeIndex
    for (var i = 0; i < jsCubeIndex.length; ++i) --jsCubeIndex[i]
    this.cubeIndexBuffer = webgl.createBuffer()
    webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, this.cubeIndexBuffer)
    webgl.bufferData(webgl.ELEMENT_ARRAY_BUFFER, new Uint8Array(jsCubeIndex), webgl.STATIC_DRAW)
    // 创建纹理
    this.textureObject = webgl.createTexture()
     webgl.bindTexture(webgl.TEXTURE_CUBE_MAP, this.textureObject)
    // 立方图纹理需要设置六个方位上的纹理，为了方便区分，我设置了六个不同的纹理图像
    webgl.texImage2D(webgl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, webgl.RGB, webgl.RGB, webgl.UNSIGNED_BYTE, img1)
    webgl.texImage2D(webgl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, webgl.RGB, webgl.RGB, webgl.UNSIGNED_BYTE, img2)
    webgl.texImage2D(webgl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, webgl.RGB, webgl.RGB, webgl.UNSIGNED_BYTE, img3)
    webgl.texImage2D(webgl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, webgl.RGB, webgl.RGB, webgl.UNSIGNED_BYTE, img4)
    webgl.texImage2D(webgl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, webgl.RGB, webgl.RGB, webgl.UNSIGNED_BYTE, img5)
    webgl.texImage2D(webgl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, webgl.RGB, webgl.RGB, webgl.UNSIGNED_BYTE, img6)
    var jsShadowPlaneData = cubedata.shadowdata
    this.shadowPlaneBuffer = webgl.createBuffer()
    webgl.bindBuffer(webgl.ARRAY_BUFFER, this.shadowPlaneBuffer)
    webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsShadowPlaneData), webgl.STATIC_DRAW)

    this.shadowMat4 = mat4.create()
    gltMakeShadowMatrix([[-1, -1, 1], [1, -1, 1], [0, -0.25, -1]], [-1, 1, 0, 1], this.shadowMat4)
    return {}
  }
  onMouseEnter = (e) => {
    var x = parseInt(e.screenX, 10)
    var y = parseInt(e.screenY, 10)
    this.angle = 0// X方向上的位移决定绕Z轴转动的角度
    this.angleX = 0// Y方向上的位移决定绕X轴转动的角度

    this.mousePosition = [x, y]
  }
  onMouseMove = (e) => {
    var x = parseInt(e.screenX, 10)
    var y = parseInt(e.screenY, 10)
    this.angle -= (x - this.mousePosition[0])// X方向上的位移决定绕Z轴转动的角度
    this.angleX -= (y - this.mousePosition[1])// Y方向上的位移决定绕X轴转动的角度

    this.mousePosition = [x, y]

    this.renderSence()
  }
  init = () => {
    this.angle = 0// X方向上的位移决定绕Z轴转动的角度
    this.angleX = 0// Y方向上的位移决定绕X轴转动的角度
    const webgl = this.refs.myCanvas.getContext('experimental-webgl')
    const vertexShaderObject = webgl.createShader(webgl.VERTEX_SHADER)
    const fragmentShaderObject = webgl.createShader(webgl.FRAGMENT_SHADER)
    this.refs.myCanvas.addEventListener('mouseenter', this.onMouseEnter)
    this.refs.myCanvas.addEventListener('mousemove', this.onMouseMove)
    const v3PositionIndex = 0
    // const cubeTexSTIndex = 1
    webgl.shaderSource(vertexShaderObject, shadervs)
    webgl.shaderSource(fragmentShaderObject, shaderfs)
    webgl.compileShader(vertexShaderObject)
    webgl.compileShader(fragmentShaderObject)

    if (!webgl.getShaderParameter(vertexShaderObject, webgl.COMPILE_STATUS)) {alert('error:vertexShaderObject') }
    if (!webgl.getShaderParameter(fragmentShaderObject, webgl.COMPILE_STATUS)) {alert('error:fragmentShaderObject') }

    const programObject = webgl.createProgram()

    webgl.attachShader(programObject, vertexShaderObject)
    webgl.attachShader(programObject, fragmentShaderObject)

    webgl.bindAttribLocation(programObject, v3PositionIndex, 'v3Position')
    
    webgl.linkProgram(programObject)
    if (!webgl.getProgramParameter(programObject, webgl.LINK_STATUS)) {alert(webgl.getProgramInfoLog(programObject))}

    this.samplerIndex = webgl.getUniformLocation(programObject, 's_texture')
    this.um4RotateIndex = webgl.getUniformLocation(programObject, 'um4Rotate')
    this.uiShadowModeIndex = webgl.getUniformLocation(programObject, 'uiShadowMode')
    this.um4ShadowIndex = webgl.getUniformLocation(programObject, 'um4Shadow')
    webgl.useProgram(programObject)
    this.loaddata()
    this.renderSence()
    
  }
  renderSence = () => {
    const webgl = this.refs.myCanvas.getContext('experimental-webgl')
    const {samplerIndex, um4RotateIndex, uiShadowModeIndex, um4ShadowIndex, textureObject, shadowPlaneBuffer, cubeBuffer, cubeIndexBuffer
    , shadowMat4} = this
    const v3PositionIndex = 0
    webgl.clearColor(0.0, 0.0, 0.0, 1.0)
    webgl.clearDepth(1.0)
    webgl.clear(webgl.COLOR_BUFFER_BIT | webgl.DEPTH_BUFFER_BIT)

    

    // webgl.bindBuffer(webgl.ARRAY_BUFFER, cubeTexSTBuffer)
    // webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, cubeIndexBuffer)
    // webgl.enableVertexAttribArray(cubeTexSTIndex)
    // webgl.vertexAttribPointer(cubeTexSTIndex, 2, webgl.FLOAT, false, 0, 0)
 
    webgl.texParameteri(webgl.TEXTURE_CUBE_MAP, webgl.TEXTURE_MIN_FILTER, webgl.NEAREST)
    webgl.texParameteri(webgl.TEXTURE_CUBE_MAP, webgl.TEXTURE_MAG_FILTER, webgl.NEAREST)
    webgl.texParameteri(webgl.TEXTURE_CUBE_MAP, webgl.TEXTURE_WRAP_S, webgl.CLAMP_TO_EDGE)
    webgl.texParameteri(webgl.TEXTURE_CUBE_MAP, webgl.TEXTURE_WRAP_T, webgl.CLAMP_TO_EDGE)

    webgl.activeTexture(webgl.TEXTURE0)
    webgl.bindTexture(webgl.TEXTURE_CUBE_MAP, textureObject)
    webgl.uniform1i(samplerIndex, 0)
 
    var m4Rotate = mat4.create()
    mat4.identity(m4Rotate)
    mat4.rotateZ(m4Rotate, this.angle * Math.PI / 180)
    mat4.rotateX(m4Rotate, this.angleX * Math.PI / 180)
    webgl.uniformMatrix4fv(um4RotateIndex, false, m4Rotate)
    webgl.enable(webgl.DEPTH_TEST)
    webgl.frontFace(webgl.CW)
    // 画平面
    webgl.disable(webgl.DEPTH_TEST) // 相当于地面，禁止深度测试，此时深度缓冲中值保持1.0不变，表示可以被任何其它物体所遮挡
    webgl.bindBuffer(webgl.ARRAY_BUFFER, shadowPlaneBuffer) 
    webgl.enableVertexAttribArray(v3PositionIndex)
    webgl.vertexAttribPointer(v3PositionIndex, 3, webgl.FLOAT, false, 0, 0)
    webgl.uniform1i(uiShadowModeIndex, 2)
    webgl.drawArrays(webgl.TRIANGLE_FAN, 0, 4)

    webgl.bindBuffer(webgl.ARRAY_BUFFER, cubeBuffer)
    webgl.bindBuffer(webgl.ELEMENT_ARRAY_BUFFER, cubeIndexBuffer)
    webgl.enableVertexAttribArray(v3PositionIndex)
    webgl.vertexAttribPointer(v3PositionIndex, 3, webgl.FLOAT, false, 0, 0)
    // 画阴影
    webgl.disable(webgl.DEPTH_TEST)// 禁止深度测试，遮挡阴影平面
    webgl.uniform1i(uiShadowModeIndex, 1)
    webgl.uniformMatrix4fv(um4ShadowIndex, false, shadowMat4)
    webgl.drawElements(webgl.TRIANGLES, 36, webgl.UNSIGNED_BYTE, 0)
    // 画立方体
    webgl.enable(webgl.DEPTH_TEST)
    webgl.depthFunc(webgl.LEQUAL)// 使用深度测试，遮挡阴影平面和阴影
    webgl.uniform1i(uiShadowModeIndex, 0)
    webgl.drawElements(webgl.TRIANGLES, 36, webgl.UNSIGNED_BYTE, 0)
  }
  render() {
    return (<div><canvas ref="myCanvas" style={{border: '1px solid red'}} width='600px' height='450px'></canvas><img ref="img1" src={Koala} />
    <img ref="img2" src={Desert} />
    <img ref="img3" src={Hydrangeas} />
    <img ref="img4" src={Lighthouse} />
    <img ref="img5" src={Jellyfish} />
    <img ref="img6" src={Penguins} /></div>)
  }
}


export default WebGL
